' This demonstrates the steps necessary to use hardware
' PWM channel 3 on the 16F767 (and similar devices).
' PBP version 2.45 is required for device support.

' Output is a 1Khz signal with duty cycle sweeping
' from 20% to 80% once per second.

' PR2 = Timer2 period register, controls PWM period.
' CCPR3L and CCP3CON<5:4>bits control the duty cycle,
' and should be treated as a 10-bit word.

' Fosc = Clock Frequency (4MHz)
' PS = Timer2 Prescale Value (T2CON<1:0>)
' Freq = PWM output frequency
' Duty% = Duty cycle (20% = 0.2)

' formulas:
' PR2=(Fosc/(4*PS*Freq))-1
' CCPR3L:CCP3CON<5:4>=(PR2+1)*4*Duty%

duty	VAR	WORD		' Duty cycle value (CCPR3L:CCP3CON<5:4>)


		TRISB.5 = 0			' Set PORTB.5 (CCP3) to output
		CCP3CON = %00001100		' Set CCP3 to PWM 
		T2CON = %00010101		' Turn on Timer2, Prescale=4

' Use formula to determine PR2 value for a 1KHz signal, 
' 4MHz clock, and prescale=4. (4E6/(4*4*1E3))-1=249

		PR2 = 249				' Set PR2 to get 1KHz out
	
' Use formula to determine CCPR3L:CCP3CON<5:4> value for
' ends of range 20% to 80%.  (249+1)*4*0.2=200 (20% value)
' (249+1)*4*0.8=800 (80% value)


		duty = 200			' Set duty cycle to 20%

loop:	CCP3CON.4 = duty.0		' Store duty to registers as
		CCP3CON.5 = duty.1		' a 10-bit word
		CCPR3L = DUTY >> 2

		duty = duty + 10		' Increase duty cycle

' Since the total sweep of duty is 600 (800-200) and 
' we are adding 10 for each loop, that results in 60
' steps min to max. 1 second divided by 60 = 16.67mS		

		Pause 17				' Pause 1/60 of second

		IF (duty < 800) Then loop	' Do it again unless 80% duty cycle

		duty = 200				' Reset to 20% duty cycle

		GoTo loop				' Do it forever
		
